require 'View.Base.BaseView'
--输入五个参数, 表示摄像机的父空间边界: LocalMaxX, LocalMaxY, LocalMinX, LocalMinY, MinCameraSize
BasePinchView = class("BasePinchView", BaseView)

function BasePinchView:OnShow()
	BaseView.OnShow(self)
	self.TouchEnable = true
	self.camera = self.gameObject:GetComponent('Camera')
	self.parent = self.transform.parent
	MultiTouchControl.EnableMultiTouch()

	self.touch0Enable = false
	self.touch1Enable = false

	self.DoPinchCo = nil
end

function BasePinchView:OnHide()
	MultiTouchControl.DisableMultiTouch()
	BaseView.OnHide(self)
end

function BasePinchView:DoPinchTo(toPos, toScale, duration)
	if self.DoPinchCo then
		coroutine.stop(self.DoPinchCo)
		self.DoPinchCo = nil
	end

	self.DoPinchCo = self:StartCoroutine(function()
		local startPos = self.transform.position
		local startScale = self.camera.orthographicSize
		local startTime = 0
		while startTime <= duration do
			coroutine.step()
			startTime = startTime + Time.deltaTime
			local ratio = math.min(1, startTime / duration)
			local pos = startPos * (1 - ratio) + toPos * ratio
			local scale = (1 - ratio) * startScale + ratio * toScale

			self.camera.orthographicSize = scale
			self:RestrictSize()
			self.transform.position = pos
			self:RestrictLocalPosition()
		end

		self.camera.orthographicSize = toScale
		self:RestrictSize()
		self.transform.position = toPos
		self:RestrictLocalPosition()
		self.DoPinchCo = nil
	end)
end

function BasePinchView:Update()
	if not self.TouchEnable or self.DoPinchCo then
		--让鼠标拖动失效
		self.lastMousePosition = nil
		return
	end

	--mouse
	if Input.GetMouseButtonDown(0) and not UnityEngine.EventSystems.EventSystem.current:IsPointerOverGameObject(-1) then
		self.lastMousePosition = Input.mousePosition
	elseif Input.GetMouseButton(0) and self.lastMousePosition then
		local mousePosition = Input.mousePosition
		local lastMousePosition = self.lastMousePosition

		local worldPosition = self.camera:ScreenToWorldPoint(Vector3(mousePosition.x, mousePosition.y, self.camera.nearClipPlane))
		local lastWorldPosition = self.camera:ScreenToWorldPoint(Vector3(lastMousePosition.x, lastMousePosition.y, self.camera.nearClipPlane))
		local diffPosition = worldPosition - lastWorldPosition

		self.transform.position = self.transform.position - diffPosition
		self:RestrictLocalPosition()

		self.lastMousePosition = mousePosition
	elseif Input.GetMouseButtonUp(0) then
		self.lastMousePosition = nil
	end

	--touch
	if UnityEngine.Input.touchCount == 1 then
		local touch = UnityEngine.Input.touches[0]
		if touch.phase == TouchPhase.Ended or UnityEngine.EventSystems.EventSystem.current:IsPointerOverGameObject(0) then
			return
		end

		local touch0Position = touch.position
		local touch0LastPosition = touch.position - touch.deltaPosition

		local worldPosition = self.camera:ScreenToWorldPoint(Vector3(touch0Position.x, touch0Position.y, self.camera.nearClipPlane))
		local lastWorldPosition = self.camera:ScreenToWorldPoint(Vector3(touch0LastPosition.x, touch0LastPosition.y, self.camera.nearClipPlane))
		local diffPosition = worldPosition - lastWorldPosition

		self.transform.position = self.transform.position - diffPosition
		self:RestrictLocalPosition()
	elseif UnityEngine.Input.touchCount == 2 then
		local touch0 = UnityEngine.Input.touches[0]
		local touch1 = UnityEngine.Input.touches[1]
		if touch0.phase == TouchPhase.Ended or UnityEngine.EventSystems.EventSystem.current:IsPointerOverGameObject(0) or
				touch1.phase == TouchPhase.Ended or UnityEngine.EventSystems.EventSystem.current:IsPointerOverGameObject(1) then
			return
		end

		local touch0Position = touch0.position
		local touch0DeltaPosition = touch0.deltaPosition
		local touch0LastPosition = touch0Position - touch0DeltaPosition

		local touch1Position = touch1.position
		local touch1DeltaPosition = touch1.deltaPosition
		local touch1LastPosition = touch1Position - touch1DeltaPosition

		--size
		local diffPosition = Vector2.Distance(touch1Position, touch0Position)
		local lastDiffPosition = Vector2.Distance(touch1LastPosition, touch0LastPosition)
		local ratio = diffPosition / lastDiffPosition
		self.camera.orthographicSize = self.camera.orthographicSize / ratio
		self:RestrictSize()

		--position
		local averagePosition = (touch0Position + touch1Position) / 2
		local lastAveragePosition = (touch0LastPosition + touch1LastPosition) / 2

		local worldPosition = self.camera:ScreenToWorldPoint(Vector3(averagePosition.x, averagePosition.y, self.camera.nearClipPlane))
		local lastWorldPosition = self.camera:ScreenToWorldPoint(Vector3(lastAveragePosition.x, lastAveragePosition.y, self.camera.nearClipPlane))
		local diffPosition = worldPosition - lastWorldPosition

		self.transform.position = self.transform.position - diffPosition
		self:RestrictLocalPosition()
	end
end

function BasePinchView:RestrictSize()
	local maxSize = math.min((self.LocalMaxY - self.LocalMinY) / 2, (self.LocalMaxX - self.LocalMinX) / 2 / self.camera.aspect)
	local size = math.min(self.camera.orthographicSize, maxSize)
	size = math.max(size, self.MinCameraSize)
	self.camera.orthographicSize = size
end

function BasePinchView:RestrictLocalPosition()
	local rightDown = self.camera:ScreenToWorldPoint(Vector3(0, 0, self.camera.nearClipPlane))
	if self.parent then rightDown = self.parent:InverseTransformPoint(rightDown) end
	local leftUp = self.camera:ScreenToWorldPoint(Vector3(UnityEngine.Screen.width, UnityEngine.Screen.height, self.camera.nearClipPlane))
	if self.parent then leftUp = self.parent:InverseTransformPoint(leftUp) end

	local displacement = Vector3.New(0, 0, 0)
	if leftUp.x < self.LocalMinX then
		displacement.x = self.LocalMinX - leftUp.x
	elseif rightDown.x > self.LocalMaxX then
		displacement.x = self.LocalMaxX - rightDown.x
	end

	if leftUp.y > self.LocalMaxY then
		displacement.y = self.LocalMaxY - leftUp.y
	elseif rightDown.y < self.LocalMinY then
		displacement.y = self.LocalMinY - rightDown.y
	end

	self.transform.localPosition = self.transform.localPosition + displacement
end